package lib

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"time"

	"../db/modes"
	"github.com/iGoogle-ink/gopay"
	"github.com/iGoogle-ink/gopay/alipay"
)

type AliPayServer struct {
	AppId           string `json:"appId"`
	PrivateKey      string `json:"privateKey"`
	AliPayPublicKey string `json:"aliPayPublicKey"`
	NotifyUrl       string `json:"notifyUrl"`

	MobileId         string `json:"mobileId"`
	MobilePublicKey  string `json:"mobilePublicKey"`
	MobilePrivateKey string `json:"mobilePrivateKey"`

	Subject    string  `json:"subject"`
	OrderNum   string  `json:"ordernum"`
	Total      float64 `json:"total"`
	SchoolName string  `json:"schoolName"`
}

type Autorated struct {
	Code       string `json:"code"`
	Msg        string `json:"msg"`
	OutTradeNo string `json:"out_trade_no"`
	QrCode     string `json:"qr_code"`
}

var AilPay AliPayServer

/*
 * 描述: 获取支付宝接口
 *
 *********************************************************************************/
func (this *AliPayServer) GoPay() (string, error) {
	// 初始化支付宝客户端
	client := alipay.NewClient(AilPay.AppId, AilPay.PrivateKey, true)

	client.SetCharset("utf-8"). // 设置字符编码，不设置默认 utf-8
		//SetSignType("RSA2").                    			// 设置签名类型，不设置默认 RSA2
		SetReturnUrl(AilPay.NotifyUrl). // 设置返回URL
		SetNotifyUrl(AilPay.NotifyUrl)  // 设置异步通知URL
	// 初始化 BodyMap
	bm := make(gopay.BodyMap)
	bm.Set("subject", AilPay.SchoolName)
	bm.Set("out_trade_no", this.OrderNum)
	bm.Set("total_amount", this.Total)

	//请求二维码
	aliRsp, err := client.TradePrecreate(bm)
	if err != nil {
		return "", nil
	}
	fmt.Println(aliRsp.SignData, aliRsp.Sign)
	//支付宝同步返回验签
	ok, _ := alipay.VerifySyncSign(AilPay.AliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
	fmt.Println(ok)
	if true == ok {
		var val Autorated
		json.Unmarshal([]byte(aliRsp.SignData), &val)
		return val.QrCode, nil
	}
	return "", nil
}

/*
 * 描述: 获取支付宝接口(APP支付场景不一样)
 *
 *********************************************************************************/
func (this *AliPayServer) AppGoPay() (string, error) {
	// 初始化支付宝客户端
	client := alipay.NewClient(AilPay.MobileId, AilPay.MobilePrivateKey, true)
	client.SetCharset("utf-8"). // 设置字符编码，不设置默认 utf-8
		//SetSignType("RSA2").                    			// 设置签名类型，不设置默认 RSA2
		SetReturnUrl(AilPay.NotifyUrl). // 设置返回URL
		SetNotifyUrl(AilPay.NotifyUrl)  // 设置异步通知URL
	// 初始化 BodyMap
	bm := make(gopay.BodyMap)
	bm.Set("subject", this.Subject)
	bm.Set("out_trade_no", this.OrderNum)
	bm.Set("total_amount", this.Total)
	//请求
	aliRsp, err := client.TradeAppPay(bm)
	fmt.Println(aliRsp, err)
	if err != nil {
		return "", nil
	}
	return base64.StdEncoding.EncodeToString([]byte(aliRsp)), nil
}

/*
 * 描述: 支付宝回调地址
 *
 *********************************************************************************/
func (this *AliPayServer) AliNotifyUrl(req *http.Request) (bool, error) {

	notifyReq, err := alipay.ParseNotifyResult(req)
	if err != nil {
		return false, nil
	}
	fmt.Println(notifyReq)
	ok, err := alipay.VerifySign(AilPay.AliPayPublicKey, notifyReq)
	fmt.Println(ok)

	if true == ok {
		var order modes.CrmOrder
		var te_class modes.TeachClass
		var st_class modes.Class
		var ord_class modes.OrderClasses
		var user modes.Employee

		//获取order_id
		order.BillNo = notifyReq.OutTradeNo
		boole, _ := order.Get()
		fmt.Println(boole, order)

		if boole == true {
			ReceiptAmount, _ := strconv.ParseFloat(notifyReq.ReceiptAmount, 64)
			if order.RealPrice != int(ReceiptAmount*100) {
				fmt.Println("订单异常实际金额与所需支付金额不符", order.BillNo)
				return false, nil
			}
			user.Id = order.UId
			if _, err := user.Get(); err != nil {
				fmt.Println("业务老师信息有误")
				return false, nil
			}

			list, _ := ord_class.List(order.Id)
			for i, _ := range list {
				te_class.Id = list[i].CId
				if fage, err := te_class.Get(); err == nil {
					if fage {
						st_class.Cid = list[i].CId
						st_class.OrderNo = order.BillNo
						boole, _ := st_class.GetClass()
						//定金不加版型信息
						if 2 != order.BillType {
							if boole == false {
								st_class.Phone, _ = strconv.ParseInt(order.Phone, 10, 64)
								st_class.CName = list[i].CName
								st_class.RealPrice = int64(order.RealPrice)
								st_class.At = time.Now().Unix()
								st_class.State = 0
								st_class.CloseAt = te_class.End
								if _, err := st_class.Save(); err != nil {
									fmt.Println("开课失败")
									return false, nil
								}
							} else {
								st_class.CloseAt = te_class.End
								if _, err := st_class.IdSet("close_at"); err != nil {
									fmt.Println("开课失败")
									return false, nil
								}
							}
						}
					}
				} else {
					fmt.Println(err.Error())
					return false, nil
				}
			}

			//班主任角色直接绑定自己ID
			if order.Teac <= 0 {
				order.State = 1
			} else {
				var crmstu modes.CrmStuden
				crmstu.Phone = order.Phone
				boole, _ := crmstu.Get()
				if boole == false {
					crmstu.Uid = order.UId
					crmstu.OrderId = order.Id
					crmstu.Name = user.Name
					crmstu.Amount = int64(order.RealPrice)
					crmstu.Note = order.Note
					crmstu.Save()
				}
				if te_class.UpgRade > 0 {
					crmstu.Senior = 1
					crmstu.IdSet("senior")
				}
				//增加班型学员数
				te_class.StudenCount(te_class.Id, 1)
				order.State = 2
			}
			//修改订单状态
			order.PayAt = time.Now().Unix()
			order.AdminId = user.Id
			order.AdminName = user.Name
			order.RealBill = notifyReq.TradeNo
			order.PayType = 2
			order.PayAt = time.Now().Unix()
			if _, err := order.IdSet("real_bill,pay_type,pay_at,state"); err != nil {
				fmt.Println("修改失败")
				return false, nil
			}

			var gloab modes.GroupGoals
			gloab.Uid = order.UId
			gloab.RealPrice += order.RealPrice / 100
			gloab.SetPrice("real_price")
			var call modes.CallPhone
			call.Phone, _ = strconv.ParseInt(order.Phone, 10, 64)
			call.State = 1
			call.IdSet("state")
			//删除工作池与首咨库里数据
			work_del_phone(order.Phone)
			fmt.Println("开课成功")
			return true, nil
		}
		return false, nil
	}
	return false, nil
}

/*
 * 描述: 删除工作池与首咨库里数据
 *
 *********************************************************************************/
func work_del_phone(phone string) error {
	var val modes.Employee
	pn, _ := strconv.ParseInt(phone, 10, 64)
	_, err := val.DelWorkPhone(pn)
	return err
}

/*
 * 描述: 初始化配置
 *
 *********************************************************************************/
func init() {
	jsonFile, err := os.Open("./config/alipay.json")
	if err != nil {
		panic("打开文件错误，请查看:" + err.Error())
	}
	defer jsonFile.Close()
	data, err := ioutil.ReadAll(jsonFile)
	json.Unmarshal(data, &AilPay)
	if _, err := AilPay.GoPay(); err != nil {
		panic("打开文件错误，请查看:" + err.Error())
	}
	fmt.Println("AilPay", AilPay)
}
